#ifndef __SUBJECT_HPP__
#define __SUBJECT_HPP__

#include <string>
#include <vector>
#include <memory>
#define OB_FUNC(__funcName__) void __funcName__( Message* msg, std::string const& eventName )


struct Message;
class Subject;
class SubjectListener;
typedef void ( Subject::*SubjectCallback )( Message*, std::string const& eventName );

struct Message {
};

class Listener {
    static std::vector< std::unique_ptr<Listener> > __pool;
public:
    char __state = 1;
    std::string eventName;
    SubjectCallback cb;
    Subject* ober;
    Listener( std::string const& eventName, SubjectCallback cb, Subject* ober );
};

class Subject {
    std::vector< Listener* > __obs;
    std::vector< Listener* > __subs;
    size_t __unuseCount = 0;

    void __listenerGc( );
public:
    Subject();
    ~Subject();
    template <typename T>
    void on( std::string const& eventName, void ( T::*cb )( Message*, std::string const& ), T* obj ) {
        Listener* listener = new Listener( eventName, (SubjectCallback)cb, obj );
        __obs.push_back( listener );
        obj->__subs.push_back( listener );
    }
    void off( Subject * ober, std::string const& eventName = "", SubjectCallback cb = nullptr );
    void emit( std::string const& eventName, Message* msg = nullptr );
    void remit( Message * msg, std::string const& eventName );
};

#endif __SUBJECT_HPP__